package com.appspot.peachykene.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.appspot.peachykene.HerbDictionary;
import com.appspot.peachykene.HerbFact;
import com.appspot.peachykene.Rb;
import com.appspot.peachykene.impl.InMemoryHerbDictionary;

/**
 * Handles Ajax requests from the main website.
 * @author kbanks
 *
 */
public class AjaxServlet extends HttpServlet {
	private static final long serialVersionUID = 8573608259121392261L;
    private static final String LANG = "lang";
    private static final String TYPE = "type";
    private static final String ARGS = "args";
    private static final String REPLY = "reply";
    
    private static final String HERBQUERY = "herbquery";
    private static final String SYMPTOMQUERY = "symptomquery";
    private static final String SYMPTOMS = "symptoms";
    private static final String HERBS = "herbs";
    private static final String LINKS = "links";
    
    private static final HerbDictionary dictionary = new InMemoryHerbDictionary();
    
	/**
	 * The incoming request will look like this:
	 * lang : en|nl
	 * args : []
	 * ctxt : "jquery selector passed back to the caller"
	 * etxt : "the jquery selector passed back to the caller if an error occurs"
	 * The response will look like this:
	 * { "html":"<html/>","ctxt":"#jquery"}
	 */
	@Override
	public void doPost(HttpServletRequest req, HttpServletResponse resp) {
		resp.setContentType("application/json; charset=UTF-8");
		String lang = req.getParameter(LANG);
		String type = req.getParameter(TYPE);
		String[] args = req.getParameterValues(ARGS);
		String msg = process(lang, type, args);

		try {
			PrintWriter out = resp.getWriter();
			
			out.write(msg);
		} catch (IOException ioe) {
			throw new RuntimeException(ioe);
		}		
	}
	
	private void handleList(StringBuilder sb, List<String> items) {
		sb.append("[");
		for(Iterator<String> iter = items.iterator(); iter.hasNext();) {
    		sb.append("\"").append(iter.next()).append("\"");
    		if(iter.hasNext()) {
    			sb.append(",");
    		}    		
    	}
		sb.append("]");
	}
	
	private String process(String lang, String type, String[] args) {
		StringBuilder sb = new StringBuilder();
		if(SYMPTOMS.equals(type)) {			
			handleList(sb, dictionary.getAllSymptoms(lang));
		} else if(HERBS.equals(type)) {
			handleList(sb, dictionary.getAllHerbNames(lang));
		} else if(HERBQUERY.equals(type)) {			
			HerbFact herb = dictionary.get(args[0].split(",",2)[0], lang);
			sb.append("\"");
			if(herb == null) {
				HerbFact.noResultsHtmlFragment(sb, lang);
			} else {
				herb.toHtmlFragment(sb, lang);
			}
			sb.append("\"");
		} else if(SYMPTOMQUERY.equals(type)) {
			Set<HerbFact> herbs = dictionary.getBySymptom(args[0], lang);
			sb.append("\"");
			if(herbs.isEmpty()) {
				HerbFact.noResultsHtmlFragment(sb, lang);
			} else {
				for(HerbFact herb : herbs) {
					herb.toHtmlFragment(sb, lang);
				}
			}
			sb.append("\"");
		} else if(LINKS.equals(type)) {
			sb.append("\"");
			StringBuilder links = new StringBuilder();
			Set<Character> usedLetters = new HashSet<Character>();
			final String backToTopLink = "<a class=\\\"toplink\\\" href=\\\"#top\\\">[Back to Top]</a>";
			for(HerbFact fact: dictionary.getAllHerbs()) {
				char letter = Character.toLowerCase(fact.getName(lang).charAt(0));
				if(usedLetters.add(letter)) {					
					if(usedLetters.size() != 1) {
						links.append(backToTopLink);
					}
					links.append("<a name=\\\"").append(letter).append("\\\"><h4>").append(Character.toUpperCase(letter)).append("</h4></a>");
				}
				fact.toLinkHtmlFragment(links, lang);
			}
			links.append(backToTopLink);
			sb.append("<ul>");
			for(char menuLetter = 'a'; menuLetter <= 'z'; menuLetter++) {			
				if(usedLetters.contains(menuLetter)) {
					sb.append("<li><a href=\\\"#").append(menuLetter).append("\\\">").append(Character.toUpperCase(menuLetter)).append("</a></li>");
				} else {
					sb.append("<li>").append(Character.toUpperCase(menuLetter)).append("</li>");
				}
			}
			sb.append("</ul>");
			sb.append(links);
			sb.append("\"");
		} else {
			error(sb, lang);
		}
		String html = sb.toString();
		String template = "{\"%s\":%s}";
		return String.format(template, REPLY, html);
	}
	
	private void error(StringBuilder sb, String lang) {
		sb.append("\"<div class=\\\"result\\\"><ul><li><h4 class=\\\"failed\\\">");
		sb.append(Rb.translate("SERVER_ERROR", lang));		
		sb.append("</h4></li></ul></div>\"");		
	}
}
